import { Directive, EmbeddedViewRef, Input, OnDestroy, TemplateRef, ViewContainerRef } from '@angular/core';
import { BaseUtils } from '../../utils';
import { Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
import { BaseAlcService } from './base-alc.service';
import { ACLCanType } from '../../types';

@Directive({
    selector: '[baseAclIf]',
    exportAs: 'baseAclIf',
})
export class BaseAclIfDirective implements OnDestroy {
    private _value: ACLCanType;
    private _change$: Subscription;
    private _thenTemplateRef: TemplateRef<void> | null = null;
    private _elseTemplateRef: TemplateRef<void> | null = null;
    private _thenViewRef: EmbeddedViewRef<void> | null = null;
    private _elseViewRef: EmbeddedViewRef<void> | null = null;

    constructor(templateRef: TemplateRef<void>, private srv: BaseAlcService, private _viewContainer: ViewContainerRef) {
        this._change$ = this.srv.change.pipe(filter(r => r != null)).subscribe(() => this._updateView());
        this._thenTemplateRef = templateRef;
    }

    @Input()
    set aclIf(value: ACLCanType) {
        this._value = value;
        this._updateView();
    }

    @Input()
    set aclIfThen(templateRef: TemplateRef<void> | null) {
        this._thenTemplateRef = templateRef;
        this._thenViewRef = null;
        this._updateView();
    }

    @Input()
    set aclIfElse(templateRef: TemplateRef<void> | null) {
        this._elseTemplateRef = templateRef;
        this._elseViewRef = null;
        this._updateView();
    }

    @Input() @BaseUtils.InputBoolean() except = false;

    protected _updateView(): void {
        const res = this.srv.can(this._value);
        if ((res && !this.except) || (!res && this.except)) {
            if (!this._thenViewRef) {
                this._viewContainer.clear();
                this._elseViewRef = null;
                if (this._thenTemplateRef) {
                    this._thenViewRef = this._viewContainer.createEmbeddedView(this._thenTemplateRef);
                }
            }
        } else {
            if (!this._elseViewRef) {
                this._viewContainer.clear();
                this._thenViewRef = null;
                if (this._elseTemplateRef) {
                    this._elseViewRef = this._viewContainer.createEmbeddedView(this._elseTemplateRef);
                }
            }
        }
    }

    ngOnDestroy(): void {
        this._change$.unsubscribe();
    }
}